package io.sdl.config;

import io.sdl.entity.TokenEntity;
import io.sdl.handler.TokenHandshakeInterceptor;
import io.sdl.service.TokenService;
import io.sdl.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.SimpAttributes;
import org.springframework.messaging.simp.SimpAttributesContextHolder;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.simp.user.DefaultUserDestinationResolver;
import org.springframework.messaging.simp.user.SimpUserRegistry;
import org.springframework.messaging.simp.user.UserDestinationResolver;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.config.annotation.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;

import java.security.Principal;
import java.util.Map;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Autowired
    private TokenService tokenService;
    @Autowired
    private UserService userService;

    @Bean // 将拦截器声明为Bean
    public TokenHandshakeInterceptor tokenHandshakeInterceptor() {
        return new TokenHandshakeInterceptor(tokenService); // 手动注入依赖
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // 启用简单内存消息代理，前缀为/topic和/queue
        config.enableSimpleBroker("/topic", "/queue");
        // 设置应用请求前缀为/app
        config.setApplicationDestinationPrefixes("/app");
        // 设置用户目的地前缀（用于点对点消息）
        config.setUserDestinationPrefix("/user");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 原生WebSocket端点
        registry.addEndpoint("/ws-native")
                .addInterceptors(tokenHandshakeInterceptor())
                .setAllowedOriginPatterns("*");

//        // SockJS端点（备用）
//        registry.addEndpoint("/ws-sockjs")
//                .setAllowedOriginPatterns("*")
//                .addInterceptors(new TokenHandshakeInterceptor())
//                .withSockJS();
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new ChannelInterceptor() {
            @Override
            public Message<?> preSend(Message<?> message, MessageChannel channel) {
                StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
                if (StompCommand.MESSAGE.equals(accessor.getCommand())) {
                    System.out.println("发送消息: " + accessor.getDestination());
                    System.out.println("目标用户: " + accessor.getUser());
                    System.out.println("消息内容: " + message.getPayload());
                }
                // 重点：处理CONNECT帧时绑定用户
                if (StompCommand.CONNECT.equals(accessor.getCommand())) {
                    // 从header获取token（兼容URL参数和Header两种方式）
                    String token = accessor.getFirstNativeHeader("token");
                    if (token == null) {
                        token = accessor.getFirstNativeHeader("Authorization");
                        if (token != null && token.startsWith("Bearer ")) {
                            token = token.substring(7);
                        }
                    }

                    // 验证token并绑定用户
                    TokenEntity tokenEntity = tokenService.getByToken(token);
                    if (tokenEntity != null) {
                        accessor.setUser(() -> tokenEntity.getUserId().toString()); // 关键绑定
                        System.out.println("用户绑定成功: " + tokenEntity.getUserId());


                    } else {
                        throw new RuntimeException("认证失败");
                    }
                }
                if (accessor.getUser() == null) {
                    Map<String, Object> sessionAttrs = accessor.getSessionAttributes();
                    if (sessionAttrs != null) {
                        Principal user = (Principal) sessionAttrs.get("user");
                        if (user != null) {
                            accessor.setUser(user);
                            System.out.println("从会话恢复用户: " + user.getName());
                        }
                    }
                }
//                accessor.setUser(() -> "1911971258096463874");
                // 打印所有STOMP操作日志
                logStompCommand(accessor);
                // 处理订阅请求
                System.out.println("处理订阅请求--->"+StompCommand.SUBSCRIBE+"------"+accessor.getCommand()+"-------"+StompCommand.SUBSCRIBE.equals(accessor.getCommand()));
                if (StompCommand.SUBSCRIBE.equals(accessor.getCommand())) {
                    handleSubscription(accessor);
                }
                return message;
            }

            // 私有方法：记录STOMP帧详情
            private void logStompCommand(StompHeaderAccessor accessor) {
                System.out.println("--- STOMP命令 ---");
                System.out.println("类型: " + accessor.getCommand());
                System.out.println("目标: " + accessor.getDestination());
                System.out.println("会话: " + accessor.getSessionId());
                System.out.println("用户: " + (accessor.getUser() != null ? accessor.getUser().getName() : "null"));
                System.out.println("头信息: " + accessor.toMap());
            }

            // 私有方法：处理订阅逻辑
            private void handleSubscription(StompHeaderAccessor accessor) {
                String destination = accessor.getDestination();
                String user = accessor.getUser() != null ? accessor.getUser().getName() : "anonymous";

                System.out.printf("【订阅验证】用户[%s]订阅路径: %s%n", user, destination);

                // 验证订阅路径格式
                if (!destination.startsWith("/user/")) {
                    System.err.println("非法订阅路径！必须以/user/开头");
                    throw new IllegalArgumentException("Invalid subscription path");
                }
            }
        });
    }



}
